﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Text;

namespace Pogo
{
   public static class Extensions
   {
      private static readonly byte[] entropy = Encoding.Unicode.GetBytes("Salt Is Not A Password");

      public static string EncryptString(this SecureString input)
      {
         string result = null;

         if (input != null)
         {
            byte[] encryptedData = ProtectedData.Protect(Encoding.Unicode.GetBytes(input.ToInsecureString()), entropy,
                                                         DataProtectionScope.CurrentUser);

            result = Convert.ToBase64String(encryptedData);
         }

         return result;
      }

      public static SecureString DecryptString(this string encryptedData)
      {
         SecureString result = null;

         if (encryptedData != null)
         {
            try
            {
               byte[] decryptedData = ProtectedData.Unprotect(Convert.FromBase64String(encryptedData), entropy,
                                                              DataProtectionScope.CurrentUser);

               result = Encoding.Unicode.GetString(decryptedData).ToSecureString();
            }
            catch
            {
               result = new SecureString();
            }
         }

         return result;
      }

      public static SecureString ToSecureString(this IEnumerable<char> input)
      {
         SecureString result = null;

         if (input != null)
         {
            SecureString secure = new SecureString();

            foreach (char c in input)
               secure.AppendChar(c);

            secure.MakeReadOnly();
            result = secure;
         }

         return result;
      }

      public static string ToInsecureString(this SecureString input)
      {
         string result = null;

         if (input != null)
         {
            IntPtr ptr = Marshal.SecureStringToBSTR(input);

            try
            {
               result = Marshal.PtrToStringBSTR(ptr);
            }
            finally
            {
               Marshal.ZeroFreeBSTR(ptr);
            }
         }

         return result;
      }
   }
}